//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2007
//
// Saved positions utilities.
//

# include "StdAfx.h"
# include "Resource.h"
# include "Favorites.h"
# include "PtAlgo.h"
# include "Position.h"
# include "Load.h"
# include "Map.h"
# include "MapView.h"
# include "ParseHelpers.h"
# include "Menu.h"
# include "EditText.h"
# include "Dialog.h"
# include "ListView.h"
# include "Settings.h"
# include "Globals.h"

typedef std::map<string_t, point_t> Favorites_t;
static Favorites_t g_Favorites;

void InitFavorites () {
	const size_t cFavorites = GetSetting ("Favorites", (DWORD) 0);
	for (size_t c = 0; c < cFavorites; ++ c) {
		char strKey [32];
		::sprintf (strKey, "Favorite_%d", c);

		char strVal [256];
		GetSetting (strKey, strVal, ARRAY_SIZE (strVal), "");

		const char * const pEnd = strVal + ::strlen (strVal);
		const char * p = strVal;
		point_t pt;
		if (! ParseReal (p, pEnd, & p, pt.x))
			continue;
		OmitSpaces (& p, pEnd);
		if (! ParseReal (p, pEnd, & p, pt.y))
			continue;
		OmitSpaces (& p, pEnd);
		if (p == pEnd)
			continue;

		const string_t strName (p);

		g_Favorites [string_t (p)] = pt;
	}

	if (g_Favorites.empty ())
		return;
	UpdateFavoritesMenu ();
}

static
void _SaveFavorites () {
	size_t cIndex = 0;
	for (Favorites_t::iterator i = g_Favorites.begin (); i != g_Favorites.end (); ++ i) {
		char strVal [256];
		::sprintf (strVal, "%0.6f %0.6f %s", i->second.x, i->second.y, i->first.c_str ());

		char strKey [32];
		::sprintf (strKey, "Favorite_%d", cIndex ++);
		SaveSetting (strKey, strVal);
	}

	SaveSetting ("Favorites", (DWORD) cIndex);

	UpdateFavoritesMenu ();
}

///////////////////////////////////////////////////

static bool g_bSeparatorAdded = false;

void UpdateFavoritesMenu () {
	// Get 'Favorites' menu.
	const HMENU hFavMenu = ::GetSubMenu (::GetMenu (g_hWnd), smFavorites);

	// Remove old favorites.
	size_t c = 0;
	while (true) {
		if (! ::RemoveMenu (hFavMenu, ID_FAVORITES_0 + c, MF_BYCOMMAND))
			break;
		++ c;
	}

	// Add menu separator (first time only).
	if (! g_Favorites.empty () && ! g_bSeparatorAdded) {
		::AppendMenu (hFavMenu, MF_SEPARATOR, 0, NULL);
		g_bSeparatorAdded = true;
	}

	// Add favorites items.
	c = 0;
	for (Favorites_t::iterator i = g_Favorites.begin (); i != g_Favorites.end (); ++ i, ++ c) {
		const bool bInsideMap = g_map.rectBound.Contains (i->second);
		::AppendMenu (
			hFavMenu,
			MF_STRING | (! bInsideMap || g_bLoading ? MF_GRAYED : MF_ENABLED),
			ID_FAVORITES_0 + c,
			i->first.c_str ()
		);
	}
}

void UpdateFavoritesMenu_Enable () {
	// Get 'Favorites' menu.
	const HMENU hFavMenu = ::GetSubMenu (::GetMenu (g_hWnd), smFavorites);

	// Add favorites items.
	size_t c = 0;
	for (Favorites_t::iterator i = g_Favorites.begin (); i != g_Favorites.end (); ++ i, ++ c) {
		const bool bInsideMap = g_map.rectBound.Contains (i->second);
		::EnableMenuItem (
			hFavMenu,
			ID_FAVORITES_0 + c,
			MF_BYCOMMAND | (! bInsideMap || g_bLoading ? MF_GRAYED : MF_ENABLED)
		);
	}
}

/////////////////////////////////////////////////

void AddToFavorites () {
	string_t strName;
	if (! EditText (g_hWnd, strName, "Favorite name", false))
		return;
	if (strName.empty ())
		return;

	point_t point;
	ScreenToPt (g_lWidth/2, g_lHeight/2, point);

	g_Favorites [strName] = point;

	_SaveFavorites ();
}

//////////////////////////////////////////////////////////

class CFavorites : public CDialog {
  public:
	CFavorites () : CDialog (IDD_FAVORITES) {}

	// Override.
	virtual bool OnInit (HWND _hwndFocus) {
		m_List.Init (m_hWnd, IDC_LIST);
		m_List.SetExtStyle (LVS_EX_FULLROWSELECT);

		AddColumn (m_List, 0, "");

		size_t cItem = 0;
		for (Favorites_t::iterator i = g_Favorites.begin (); i != g_Favorites.end (); ++ i)
			InsertItem (m_List, cItem ++, reinterpret_cast<LPARAM> (i->first.c_str ()), "%s", i->first.c_str ());

		AutoSizeColumns (m_List);

		return true;
	}

	virtual void OnCommand (WORD _wCmd, WORD _wNotifyCode, HWND _hwndCtl) {
		switch (_wCmd) {
			case IDOK: {
				const size_t cItems = ListView_GetItemCount (m_List);
				for (size_t c = 0; c < cItems; ++ c) {
					if (ListView_GetItemState (m_List, c, LVIS_SELECTED)) {
						const char * strName = reinterpret_cast<const char *> (GetLParam (m_List, c));
						g_Favorites.erase (strName);
					}
				}

				_SaveFavorites ();
			}
			case IDCANCEL:
				EndDialog (0);
				break;
		}
	}

  private:
	CListView m_List;
};

void RemoveFavorite () {
	CFavorites ().ShowModal (g_hWnd);
}

void GoToFavorite (size_t _cIdx) {
	size_t c = 0;
	for (Favorites_t::iterator i = g_Favorites.begin (); i != g_Favorites.end (); ++ i, ++ c)
		if (c >= _cIdx) {
			SetToCenter (i->second);
			Refresh ();
			return;
		}
}